package com.xhj.mybatis.reflection.invoker;

import com.xhj.mybatis.reflection.Reflector;

import java.lang.reflect.Field;

/**
 * SetFieldInvoker
 *
 * @author XJks
 * @description 用于设置对象字段值的调用器
 */
public class SetFieldInvoker implements Invoker {
    /**
     * 用于保存需要操作的字段（Field 对象）
     */
    private final Field field;

    /**
     * 构造方法，接收一个 Field 对象并赋值给成员变量
     *
     * @param field 需要操作的字段
     */
    public SetFieldInvoker(Field field) {
        this.field = field;
    }

    /**
     * 实现 Invoker 接口的 invoke 方法，用于设置字段的值
     *
     * @param target 表示要调用方法的对象
     * @param args   参数 args 表示调用方法时传递的参数数组
     * @return 返回值为 null，因为设置字段值的方法没有返回值
     * @throws IllegalAccessException 如果没有权限访问该字段
     */
    @Override
    public Object invoke(Object target, Object[] args) throws IllegalAccessException {
        try {
            // 尝试直接设置 target 对象的 field 字段为 args[0] 的值
            field.set(target, args[0]);
        } catch (IllegalAccessException e) {
            // 如果没有权限访问该字段，捕获异常
            if (Reflector.canControlMemberAccessible()) {
                // 如果可以通过反射修改可访问性，则设置字段可访问
                field.setAccessible(true);
                // 再次尝试设置字段的值
                field.set(target, args[0]);
            } else {
                // 如果不能修改可访问性，则抛出异常
                throw e;
            }
        }
        // 设置字段值的方法没有返回值，这里返回 null
        return null;
    }

    /**
     * 实现 Invoker 接口的 getType 方法，返回字段的类型
     *
     * @return 字段的类型
     */
    @Override
    public Class<?> getType() {
        return field.getType();
    }
}
